package com.feib.soeasy.action;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import com.feib.soeasy.model.Group;
import com.feib.soeasy.model.Payment;
import com.feib.soeasy.pagination.PaginatedList;
import com.feib.soeasy.service.GroupService;
import com.feib.soeasy.service.PaymentService;
import com.feib.soeasy.util.UserUtil;
import com.lowagie.text.pdf.PdfCopyFields;
import com.lowagie.text.pdf.PdfReader;


import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontBind;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.DateTypeConverter;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidationErrorHandler;
import net.sourceforge.stripes.validation.ValidationErrors;

/**
 * @title (#)Soez3001ActionBean.java <br>
 * @description 區間帳單列印 Controller<br>
 * @author Leo Lee
 * @version 1.0.0 2010/11/30
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/11/30 create by Leo Lee<br>
 */
public class Soez3001ActionBean extends BaseActionBean implements ValidationErrorHandler {

	/**
	 * 區間帳單列印畫面
	 */
	private static final String DEFAULT_JSP = "/WEB-INF/views/soez3001/soez3001.jsp";
	/**
	 * 業者代號查詢畫面
	 */
	private static final String AJAX_QUERY_GROUP_JSP = "/WEB-INF/views/soez3001/groupPopUpList.jsp";

	/**
	 * [業者代號]改變後觸發重製[收款類別]選項結果
	 */
	private static final String AJAX_FORMT_DEF_OPTIONS_JSP = "/WEB-INF/views/soez9004/formatDefinitionOptions.jsp";

	/**
	 * 繳費清單畫面
	 */
	private static final String LIST_JSP = "/WEB-INF/views/soez3001/soez3001List.jsp";

	/**
	 * 繳費單明細畫面
	 */
	private static final String PAYMENT_ITEM_JSP = "/WEB-INF/views/soez2005/paymentList.jsp";

	/**
	 * 帳單業者查詢條件
	 */
	private Group qryGroup;

	/**
	 * 帳單業者查詢結果
	 */
	private PaginatedList<Group> queryGroupResult;

	/** 
	 * 查詢條件-上傳日期起
	 */
	//@Validate( required=true, on={"doAjaxQuery"}, converter=DateTypeConverter.class)
	private Date qryPayDueFrom;

	/**
	 * 查詢條件-上傳日期迄
	 */
	//@Validate( required=true, on={"doAjaxQuery"}, converter=DateTypeConverter.class)
	private Date qryPayDueTo;
	/**
	 * 查詢條件-繳費帳號起
	 */    
	//@Validate(required=true , on={"doAjaxQuery"})
	private String qryVirtualAccountFrom;
	/**
	 * 查詢條件-繳費帳號迄
	 */
	//@Validate(required=true, on={"doAjaxQuery"})
	private String qryVirtualAccountTo;
	/**
	 * 業者代號
	 */
	@Validate(required=true, on={"doAjaxQuery"})
	private String qryGroupNo;

	private String overCountMessage;


	/**
	 * 查詢結果
	 */
	private List<Payment> queryResult;

	/**
	 * 查詢單筆Payment
	 */
	private Payment resultPayment;


	private String reason;

	/**
	 * 查詢條件
	 */
	private Payment qryPayment;

	@SpringBean("groupService")
	private GroupService groupService;


	/**
	 * 檔案帳單明細查詢結果
	 */
	private PaginatedList<Payment> queryPaymentResult;

	/**
	 * 畫面選取繳費單
	 */
	private ArrayList<Payment> checkPayment ;


	@SpringBean("paymentService")
	private PaymentService paymentService;

	/**
	 * 暫存目錄
	 */
	@SpringBean("tempDirectory")
	private String tempDirectory;




	@DontBind
	@DefaultHandler
	public Resolution doDefault()
	{
		logger.debug("Enter doDefault mehtod.");
		try {
			Calendar cal = Calendar.getInstance();
			//qryPayDueTo = cal.getTime();
			cal.add(Calendar.MONTH,-1);
			//qryPayDueFrom = cal.getTime();
		}
		catch (Exception e) {
		}
		return new ForwardResolution(DEFAULT_JSP); 
	}



	public Resolution doAjaxQuery()
	{
		logger.debug("Enter doAjaxQuery mehtod.");
		try {
			if (null == qryPayment)
				qryPayment = new Payment();

			// 查上傳人員與目前使用者同一個Group 的案件
			if (!UserUtil.isBankGroup())
			{
				Group group = new Group();
				group.setGroupPk(UserUtil.getUserGroup().getGroupPk());
				qryPayment.setGroup(group);
			} else
			{
				logger.debug("Enter doAjaxQuery mehtod. qryGroupNo {}",qryGroupNo);
				qryPayment.setGroup(groupService.findByExactGroupNo(qryGroupNo));
			}


			//呼叫服務查詢
			List<Payment> payments = 
				paymentService.queryDownloadPayments(
						qryPayment, qryPayDueFrom, qryPayDueTo, 
						qryVirtualAccountFrom, qryVirtualAccountTo);

			if(payments.size() > 200)
			{
				overCountMessage = "繳費單筆數超過200筆, 請重新查詢";
				return new ForwardResolution(LIST_JSP); 
			}
			else if(payments.size() == 0)
			{
				overCountMessage = "查無繳費單, 請重新查詢";
				return new ForwardResolution(LIST_JSP);           	
			} 

			queryResult =payments;

		}catch (Exception e) {
			logger.error("區間帳單列印查詢錯誤(Soez3001ActionBean.doAjaxQuery):", e);

			// 轉換錯誤訊息
			ValidationErrors errors = new ValidationErrors();
			errors.addGlobalError(new LocalizableError("doDefulat.exception") );
			getContext().setValidationErrors(errors);
			// 回傳 錯誤 HTML fragments
			return super.errorsToHtmlStreams(errors);
		}
		return new ForwardResolution(LIST_JSP);
	}


	/**
	 * 帳單明細查詢
	 * @return
	 */
	public Resolution doAjaxQueryPayments()
	{
		if (null == qryPayment)
			qryPayment = new Payment();

		logger.debug("Enter doAjaxQueryPayments mehtod.");
		try {
			resultPayment = 
				paymentService.getPaymentByPk(qryPayment);
		}
		catch (Exception e) {
			logger.error("", e);

			// 轉換錯誤訊息
			ValidationErrors errors = new ValidationErrors();
			errors.addGlobalError(new LocalizableError("doAjaxQueryPaymentsAction.exception") );
			getContext().setValidationErrors(errors);
			// 回傳 錯誤 HTML fragments
			return super.errorsToHtmlStreams(errors);
		}
		return new ForwardResolution(PAYMENT_ITEM_JSP);
	}

	/**
	 * 帳單下載(包含單隻與合併)
	 * @return
	 */
	public Resolution doDownloadAction()
	{
		logger.debug("Enter doAjaxDownloadAction mehtod.");
		try { 


			if (null == checkPayment)
				checkPayment = new ArrayList<Payment>();

			/* 中租可能多帳號對應同一個繳費單,故用set排除重複來源pdf */
			Set<String> payments=new  HashSet<String>();
			/* 避免CHECKBOX跳號勾選*/
			for(Payment  payment :checkPayment){
				if(null!=payment){
					if(null!=payment.getPdfFilePathOnServer()){
						payments.add(payment.getPdfFilePathOnServer());
						logger.debug("payment.getPdfFilePathOnServer() {}",payment.getPdfFilePathOnServer());
					} 
				}

			}

			String tempDownloadFilePath = tempDirectory + "/" + UserUtil.getUserGroup().getGroupNo() + "/" + UserUtil.getUserId() + "/";  

			File file = new File(tempDownloadFilePath);    		
			if(!file.exists())
			{
				file.mkdirs();
			}

			String downloadFilePath = tempDownloadFilePath + UUID.randomUUID().toString() + "-margePdfFile.pdf";
			mergePDF(downloadFilePath, payments);

			File downloadFile = new File(downloadFilePath);
			byte[] bytes = new byte[(int)downloadFile.length()];

			BufferedInputStream bufferedInputStream = 
				new BufferedInputStream(new FileInputStream(downloadFile)); 

			bufferedInputStream.read(bytes);

			ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
			inputStream.close();
			bufferedInputStream.close();

			String isoFileName = new String("區間帳單列印.pdf".getBytes("MS950"), "ISO8859-1");

			StreamingResolution streamingResolution = new StreamingResolution( 
					"application/pdf",inputStream).setFilename(isoFileName);

			return streamingResolution;

		}
		catch (Exception e) {
			logger.error("區間帳單列印錯誤(Soez3001ActionBean.doAjaxDownloadAction):", e);

			// 轉換錯誤訊息
			ValidationErrors errors = new ValidationErrors();
			errors.addGlobalError(new LocalizableError("doAjaxDownloadAction.exception") );
			getContext().setValidationErrors(errors);
			// 回傳 錯誤 HTML fragments
			return super.errorsToHtmlStreams(errors);
		}
	}

	/**
	 * 帳單業者查詢
	 * @return
	 */
	public Resolution doAjaxQueryGroups()
	{
		logger.debug("Enter doAjaxQueryGroups mehtod.");
		try {
			//如果不是銀行端，則查詢條件要加入帳單業者限制
			if (!UserUtil.isBankGroup())
			{
				throw new Exception("No Authority");
			}


			//USER未輸入查詢條件，所以查詢物件會是NULL(查詢物件不可為NULL)
			if (null == qryGroup)
				qryGroup = new Group();

			//呼叫服務查詢
			queryGroupResult = groupService.queryByGroupExcludeBank(qryGroup, queryGroupResult);
		}
		catch (Exception e) {
			logger.error("帳單上傳記錄查詢-帳單業者查詢錯誤(Soez9004ActionBean.doAjaxQueryGroups):", e);

			// 轉換錯誤訊息
			ValidationErrors errors = new ValidationErrors();
			errors.addGlobalError(new LocalizableError("doAjaxQuery.exception") );
			getContext().setValidationErrors(errors);
			// 回傳 錯誤 HTML fragments
			return super.errorsToHtmlStreams(errors);
		}

		return new ForwardResolution(AJAX_QUERY_GROUP_JSP);
	}


	public void mergePDF(String mergePdfName, Set<String> paymentPdfNames)
	{
		try {
			PdfCopyFields copy = new PdfCopyFields(new FileOutputStream(mergePdfName));
			copy.open();
			String pageNOs = "";

			for(String paymentPdfName:paymentPdfNames)
			{
				PdfReader reader = 
					new PdfReader(paymentPdfName);
				int noOfPages = reader.getNumberOfPages();

				if (noOfPages > 0) 
				{
					pageNOs = getNumderOfPages(noOfPages);
				}
				copy.addDocument(reader, pageNOs);		

			}
			copy.close();
		} catch (Exception e) {
			logger.error("帳單上傳記錄查詢錯誤(Soez9004ActionBean.mergePDF):", e);
		}

	}

	public String getNumderOfPages(int noOfPages) {
		String pageNOs = "";
		boolean flag = false;
		for (int i = 0; i < noOfPages; i++) {

			if (flag == true) {
				Integer c = (Integer) i;
				pageNOs = pageNOs.concat("," + c.toString());
			}
			if (flag == false) {
				Integer c = (Integer) i;
				pageNOs = c.toString();
				flag = true;
			}
		}
		return pageNOs;
	}


	public Resolution doAjaxGroupNoChange()
	{
		return new ForwardResolution(AJAX_FORMT_DEF_OPTIONS_JSP);
	}


	public List<Payment> getQueryResult() {
		return queryResult;
	}



	public void setQueryResult(List<Payment> queryResult) {
		this.queryResult = queryResult;
	}
	public Payment getResultPayment() {
		return resultPayment;
	}



	public void setResultPayment(Payment resultPayment) {
		this.resultPayment = resultPayment;
	}



	public String getQryVirtualAccountFrom() {
		return qryVirtualAccountFrom;
	}



	public void setQryVirtualAccountFrom(String qryVirtualAccountFrom) {
		this.qryVirtualAccountFrom = qryVirtualAccountFrom;
	}



	public String getQryVirtualAccountTo() {
		return qryVirtualAccountTo;
	}



	public void setQryVirtualAccountTo(String qryVirtualAccountTo) {
		this.qryVirtualAccountTo = qryVirtualAccountTo;
	}



	public String getOverCountMessage() {
		return overCountMessage;
	}



	public void setOverCountMessage(String overCountMessage) {
		this.overCountMessage = overCountMessage;
	}



	public String getQryGroupNo() {
		return qryGroupNo;
	}



	public void setQryGroupNo(String qryGroupNo) {
		this.qryGroupNo = qryGroupNo;
	}



	public Group getQryGroup() {
		return qryGroup;
	}



	public void setQryGroup(Group qryGroup) {
		this.qryGroup = qryGroup;
	}



	public PaginatedList<Group> getQueryGroupResult() {
		return queryGroupResult;
	}



	public void setQueryGroupResult(PaginatedList<Group> queryGroupResult) {
		this.queryGroupResult = queryGroupResult;
	}

	public Date getQryPayDueFrom() {
		return qryPayDueFrom;
	}



	public void setQryPayDueFrom(Date qryPayDueFrom) {
		this.qryPayDueFrom = qryPayDueFrom;
	}



	public Date getQryPayDueTo() {
		return qryPayDueTo;
	}



	public void setQryPayDueTo(Date qryPayDueTo) {
		this.qryPayDueTo = qryPayDueTo;
	}


	public String getReason() {
		return reason;
	}



	public void setReason(String reason) {
		this.reason = reason;
	}


	public PaginatedList<Payment> getQueryPaymentResult() {
		return queryPaymentResult;
	}



	public void setQueryPaymentResult(PaginatedList<Payment> queryPaymentResult) {
		this.queryPaymentResult = queryPaymentResult;
	}


	public Payment getQryPayment() {
		return qryPayment;
	}


	public void setQryPayment(Payment qryPayment) {
		this.qryPayment = qryPayment;
	}


	public ArrayList<Payment> getCheckPayment() {
		return checkPayment;
	}


	public void setCheckPayment(ArrayList<Payment> checkPayment) {
		this.checkPayment = checkPayment;
	}

}
